// 使用代理模式OOP实现的单例模式
// 单例类
class SingleInstance<T extends Object>{
    instance: T
    constructor(obj: T) {
        this.instance = obj;
    }
}
// 单例代理函数
const proxySingleInstance = (function <T>() {
    let instance: SingleInstance<T> | null = null;
    return function (obj: T) {
        // 判断单例是否存在
        if (instance !== null) {
            return instance;
        } else {
            instance = new SingleInstance<T>(obj);
            return instance;
        }
    };
})();

// 测试用例
let person = {
    name: 'leon',
    age: 18
};

let person1 = proxySingleInstance(person);
let person2 = proxySingleInstance(person);
// 返回的其实是相同的单例 true
console.log(person1 === person2);


// 对象的字面量
const namespace1 = {
    a() {
        console.log('this is methodA')
    },
    b() {
        console.log('this is methodB')
    }
};

// 使用闭包封装私有变量
const user = (function () {
    let __userId: number = 0;
    let __userName: string = '';
    return {
        getName() {
            return __userName;
        },
        getId() {
            return __userId;
        },
        setId(num: number) {
            __userId = num;
        },
        setName(name: string) {
            __userName = name;
        }
    }
})();

// 测试用例
console.log(user.getId());// 0
user.setId(1001);
console.log(user.getId());// 1001

// 通用惰性单例
const getSingleInstance = function <T extends () => any>(createInstance: T) {
    type instanceType = ReturnType<T> | null;
    let instance: instanceType = null;
    return function (this: unknown) {
        if (instance === null) {
            instance = createInstance.apply(this);
        }
        return instance!;
    }
}

// 测试用例
// 创建登录页函数
function loginFactory() {
    const divTag: HTMLDivElement = document.createElement('div');
    divTag.textContent = `欢迎登陆`;
    divTag.style.display = 'none';
    // 剩余的一些逻辑
    document.body.appendChild(divTag);
    return divTag;
}
// 创建登录页单例函数
const loginBySingleInstance = getSingleInstance(loginFactory);
// 无论如何都至多创建一个弹窗
document.getElementById('myBtn')!.onclick = function () {
    loginBySingleInstance().style.display = 'block';
};



// 执行某段逻辑
const implemeteSomeLogicOnceOnly = getSingleInstance(() => {
    console.log('执行了某段逻辑');
    return true;
});
// 只会执行一次
implemeteSomeLogicOnceOnly();
implemeteSomeLogicOnceOnly();
implemeteSomeLogicOnceOnly();
